﻿using MediatR;
using Microsoft.Extensions.Logging;
using Ordering.API.Application.IntegrationEvents;
using Ordering.API.Application.IntegrationEvents.Events;
using Ordering.Domain.AggregatesModel.OrderAggregate;
using Ordering.Infrastructure.Idempotency;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Ordering.API.Application.Commands
{
    public class CompletedOrderCommandHandler
    : IRequestHandler<CompletedOrderCommand, bool>
    {
        private readonly IOrderRepository _orderRepository;
        private readonly IMediator _mediator;
        private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;
        private readonly ILogger<CompletedOrderCommandHandler> _logger;

        public CompletedOrderCommandHandler(IMediator mediator,
            IOrderingIntegrationEventService orderingIntegrationEventService,
            IOrderRepository orderRepository,
            ILogger<CompletedOrderCommandHandler> logger)
        {
            _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
            _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
            _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }
        public async Task<bool> Handle(CompletedOrderCommand message, CancellationToken cancellationToken)
        {
            // Add Integration event 
            var orderIntegrationEvent = new OrderStatusChangedToCompletedIntegrationEvent(message.OrderNO);
            await _orderingIntegrationEventService.AddAndSaveEventAsync(orderIntegrationEvent);
            var order = await _orderRepository.GetByOrderNOAsync(message.OrderNO);
            if (order != null)
            {
                order.SetCancelledStatus();
            }
            _logger.LogInformation("----- Cancel Order - Order: {@Order}", order);
            return await _orderRepository.UnitOfWork
                .SaveEntitiesAsync(cancellationToken);
        }
    }
    public class CompletedOrderIdentifiedCommandHandler : IdentifiedCommandHandler<CompletedOrderCommand, bool>
    {
        public CompletedOrderIdentifiedCommandHandler(
            IMediator mediator,
            IRequestManager requestManager,
            ILogger<IdentifiedCommandHandler<CompletedOrderCommand, bool>> logger)
            : base(mediator, requestManager, logger)
        {
        }

        protected override bool CreateResultForDuplicateRequest()
        {
            return true;                // Ignore duplicate requests for canceling order.
        }
    }
}
